﻿Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Text
Imports System.Windows.Forms

Public Class PTIC_TabControl
    Inherits TabControl

#Region "Appels API"

    Public Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As IntPtr, ByVal hRgn As IntPtr, ByVal bRedraw As Boolean) As IntPtr

#End Region

#Region "Variables privées"

    Private Const _Int_TabDecalage As Int32 = -5
    Private Const _Int_TabPath_Rayon As Int32 = 5
    Private Const _Int_TabPath_Diametre As Int32 = 10

    Private _Type As EnumType

    'Définition des variables nécessaires au dessin
    Dim myRegion As Region


    Public Enum EnumType
        Defaut = 0
        Creux = 1
    End Enum

    Private _Border As Boolean

    'Private _Couleurs As Color() = {Color.FromArgb(175, 210, 255), Color.Blue, Color.Green, Color.FromArgb(227, 239, 255), Color.Yellow, Color.FromArgb(175, 210, 255), _
    ' Color.MediumPurple}

    Private _Couleurs As Color() = {Color.FromArgb(175, 210, 255)}

#End Region

#Region "Création d'une instance"

    Public Sub New()

        'Définition des styles d'affichage pour éviter le flicking
        SetStyle(ControlStyles.UserPaint, True)
        SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        SetStyle(ControlStyles.Opaque, True)
        SetStyle(ControlStyles.ResizeRedraw, True)

        _Border = True
        myRegion = Nothing
    End Sub

#End Region

#Region "Propriétés"

    ''' <summary>
    ''' Type utilisé pour la représentation du control
    ''' </summary>
    Public Property Type() As EnumType
        Get
            Return _Type
        End Get
        Set(ByVal value As EnumType)
            Select Case value
                Case EnumType.Creux
                    If True Then
                        'Reinit de l'allignement de text
                        Me.Alignment = TabAlignment.Top
                        Exit Select
                    End If
                Case Else
                    If True Then
                        'ras
                        Exit Select
                    End If
            End Select
            _Type = value
            Refresh()
        End Set
    End Property

    ''' <summary>
    ''' Afficher ou non le cadre des tabpages
    ''' </summary>
    Public Property Border() As [Boolean]
        Get
            Return _Border
        End Get
        Set(ByVal value As [Boolean])
            _Border = value
            Refresh()
        End Set
    End Property

#End Region

#Region "Redéfinition de la méthode paint"

    ''' <summary>
    ''' Méthode paint
    ''' </summary>
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

        Try
            Dim myNewRegion As Region = Nothing
            If TabPages.Count = 0 Then
                Exit Sub
            End If
            Dim i As Int32
            Dim P As Point() = New Point(1) {}
            Dim Rect_Tab0 As Rectangle

            'Couleurs d'arrière plan
            TabPages(SelectedIndex).BackColor = Styles.Instance.ColorBack
            e.Graphics.Clear(Styles.Instance.ColorBack)

            'Boutons tabs
            For i = TabPages.Count - 1 To 0 Step -1
                If Not i.Equals(SelectedIndex) Then
                    'Dessine l'onglet et l'ajoute à MyRegion
                    DrawTab(i, e.Graphics, myNewRegion)
                End If
            Next

            'Bouton tab qui se trouve au dessus des autres (celui qui est selected
            DrawTab(SelectedIndex, e.Graphics, myNewRegion)


            'Dessin du cadre
            Rect_Tab0 = GetTabRect(0)
            Select Case Alignment
                Case TabAlignment.Left
                    P(0).X = Rect_Tab0.X + Rect_Tab0.Width
                    P(0).Y = Rect_Tab0.Y
                    P(1).X = e.ClipRectangle.X + e.ClipRectangle.Width - 1
                    P(1).Y = e.ClipRectangle.Y + e.ClipRectangle.Height - 1
                    Exit Select
                Case Else
                    Select Case _Type
                        Case EnumType.Creux
                            P(0).X = e.ClipRectangle.X
                            P(0).Y = e.ClipRectangle.Y
                            P(1).X = e.ClipRectangle.X + e.ClipRectangle.Width - 1
                            P(1).Y = e.ClipRectangle.Y + e.ClipRectangle.Height - 1
                            Exit Select
                        Case Else
                            'P(0).X = Rect_Tab0.X
                            'P(0).Y = Rect_Tab0.Y + Rect_Tab0.Height
                            'P(1).X = Me.Width - 1
                            'P(1).Y = Me.Height - 1
                            Exit Select
                    End Select
                    Exit Select
            End Select

            'Dans le cas d'un control avec bordure on dessine la bordure
            If _Border Then
                'SelectedTab.
                'DisplayRectangle.
                'e.Graphics.DrawRectangle(Styles.Instance.PenBorders, P(0).X, P(0).Y, P(1).X - P(0).X, P(1).Y - P(0).Y)
            End If

            'On ajoute la zone cliente à la région du contrôle
            myNewRegion.Union(Me.DisplayRectangle)
            SetWindowRgn(Me.Handle, myNewRegion.GetHrgn(e.Graphics), True)

        Catch
            ' RAS -> Capture pour le mode debug qui peu pauser soucis
            ''MsgBox("Erreur")
        End Try
    End Sub

    ''' <summary>
    ''' Dessin d'un item Tab
    ''' </summary>
    ''' <param name="Index"></param>
    ''' <param name="G"></param>
    Private Sub DrawTab(ByVal Index As Int32, ByVal G As Graphics, ByRef myRegion As Region)

        'Récupération du rectangle lié à l'onglet
        Dim Rec As Rectangle = GetTabRect(Index)

        Dim Color_BG As Color
        Dim ColorBorders As Color

        Dim Font_Text As Font
        Dim Format_Text As New StringFormat()

        Dim G_path As GraphicsPath

        'Premier onglet
        If Index = 0 AndAlso Alignment = TabAlignment.Top Then
            Rec = New Rectangle(Rec.X - _Int_TabDecalage, Rec.Y, Rec.Width + _Int_TabDecalage, Rec.Height)
        End If

        'Autres onglets
        If Me.SelectedIndex = Index Then
            'Int_Offset = 2;
            Font_Text = New Font(Font, FontStyle.Bold) ' FontStyle.Underline Or FontStyle.Bold)
            G_path = TabPath(Rec, myRegion)

            For i As Int32 = 3 To 1 Step -1
                G.FillPath(New SolidBrush(Color.FromArgb(Convert.ToInt32(100 / 3 * i), Color.Black)), TabPath(New Rectangle(Rec.X + i, Rec.Y + i, Rec.Width, Rec.Height - i), myRegion))
            Next
        Else
            Font_Text = New Font(Font, FontStyle.Regular)
            G_path = TabPath(Rec, myRegion)
        End If

        'Définition de la couleur de fonds de l'onglet
        If Me.SelectedIndex <> Index Then
            ''Color_BG = My.Settings.AEROColor_BackDegrade
            ''Color_BG = Color.FromArgb(175, 210, 255)
            ''Color_BG = Color.FromArgb(210, 220, 230)
            ''Color_BG = My.Settings.OMANEBtnSTD_ColorDegrade
            Color_BG = Color.FromArgb(220, 185, 255) 'Couleur OMANE (231;213;231)
            ''Color_BG = Color.FromArgb(255, 230, 30)
            ''Color_BG = Color.FromArgb(241, 234, 116)
            ''Color_BG = Color.FromArgb(237, 221, 207)
            ''Color_BG = Color.FromArgb(79, 139, 43)
            ''Color_BG = Color.FromArgb(179, 221, 220)
            ''Color_BG = Color.FromArgb(212, 225, 242)
            ''Color_BG = Color.FromArgb(232, 171, 182)
            ColorBorders = My.Settings.OMANEBtnSTD_ColorBorder
        Else
            Color_BG = My.Settings.OMANEBtnMOUSEOVER_ColorDegrade
            ColorBorders = My.Settings.OMANEBtnMOUSEOVER_ColorBorder
        End If

        'Mode de dessin
        G.InterpolationMode = InterpolationMode.HighQualityBilinear
        G.SmoothingMode = SmoothingMode.AntiAlias

        'Style glossy
        Dim Rect_Style As Rectangle = Rec
        Select Case Alignment
            Case TabAlignment.Top
                Rect_Style.Inflate(5, 0)
                Rect_Style.Offset(-5, 0)
                Exit Select
            Case TabAlignment.Left
                Rect_Style.Inflate(0, 10)
                Exit Select
        End Select

        Styles.PaintBackAeroGlassOMANE(G, Rect_Style, Color_BG, G_path)

        'Bords
        G.DrawPath(New Pen(ColorBorders), G_path)

        'alignement du text
        Format_Text.Alignment = StringAlignment.Center
        Format_Text.LineAlignment = StringAlignment.Center

        Select Case Alignment
            Case TabAlignment.Left
                G.TranslateTransform(Rec.X, Rec.Height + Rec.Y * 2)
                G.RotateTransform(-90)
                'Ecritue du text
                G.DrawString(TabPages(Index).Text, Font_Text, Brushes.Black, Rec.Y, Rec.X)
                G.ResetTransform()
                Exit Select
            Case Else
                'Ecriture du text
                Dim recString As New Rectangle(Rec.X + 8, Rec.Y, Rec.Width - 8, Rec.Height)
                G.DrawString(TabPages(Index).Text, _
                             Font_Text, _
                             Brushes.Black, _
                             recString, _
                             Format_Text)


                'G.DrawString(TabPages(Index).Text, _
                '             Font_Text, _
                '             Brushes.Black, _
                '             Rect_Style.X + 5, _
                '             Rect_Style.Y + (Rect_Style.Height - SizeTxt.Height) / 2, _
                '             Format_Text)

                Exit Select
        End Select

        ''Dim r As Region = New Region(G_path)
        ''Dim Int_Heiht As Int32 = Convert.ToInt32(Rect_Style.Height / 2)
        ''Dim rect1 = New Rectangle(Rect_Style.X, Rect_Style.Y, Rect_Style.Width, Int_Heiht)
        ''Dim rect2 = New Rectangle(Rect_Style.X, Rect_Style.Y + Int_Heiht, Rect_Style.Width, Rect_Style.Height - Int_Heiht)
        ''r.Intersect(rect1)
        ''myRegion.Union(r)
        ''r = New Region(G_path)
        ''r.Intersect(rect2)
        ''myRegion.Union(r)


        'Libértations mémoire
        If Font_Text IsNot Nothing Then
            Font_Text.Dispose()
        End If
        Font_Text = Nothing

        If Format_Text IsNot Nothing Then
            Format_Text.Dispose()
        End If
        Format_Text = Nothing

        If G_path IsNot Nothing Then
            G_path.Dispose()
        End If

        G_path = Nothing
    End Sub

    ''' <summary>
    ''' Permet d'obtenir une forme qui sert au tracé d'un tab
    ''' </summary>
    ''' <param name="Rect"></param>
    ''' <returns></returns>
    Private Function TabPath(ByVal Rect As Rectangle, ByRef myRegion As Region) As GraphicsPath

        Dim Rect_Angle As New Rectangle(Rect.Location, New Size(_Int_TabPath_Diametre, _Int_TabPath_Diametre))

        Dim Path As New GraphicsPath()

        Try
            Select Case Alignment
                Case TabAlignment.Left
                    If True Then
                        Rect_Angle.X = Rect.X
                        Rect_Angle.Y = Rect.Y + Rect.Height - _Int_TabDecalage - _Int_TabPath_Diametre - 5
                        Path.AddArc(Rect_Angle, 120, 60)

                        Rect_Angle.Y = Rect.Y + _Int_TabDecalage + _Int_TabPath_Rayon
                        Path.AddArc(Rect_Angle, 180, 90)

                        Path.AddLine(Rect.X + Rect.Width, Rect.Y, Rect.X + Rect.Width, Rect.Y + Rect.Height - _Int_TabDecalage)
                        Exit Select
                    End If

                Case TabAlignment.Right
                    If True Then
                        Rect_Angle.X = Rect.X + Rect.Width - _Int_TabPath_Diametre
                        Rect_Angle.Y = Rect.Y
                        Path.AddArc(Rect_Angle, 270, 90)

                        Rect_Angle.Y = Rect.Y + Rect.Height - _Int_TabPath_Diametre
                        Path.AddArc(Rect_Angle, 0, 90)

                        Path.AddLine(Rect.X, Rect.Y + Rect.Height, Rect.X, Rect.Y)
                        Exit Select
                    End If
                Case Else
                    'Differenciation des types
                    Select Case _Type
                        Case EnumType.Creux
                            Path.AddLine(Rect.X + _Int_TabDecalage, Rect.Y, Rect.X + Rect.Width, Rect.Y)

                            Rect_Angle.X = Rect.X + Rect.Width - _Int_TabPath_Diametre + _Int_TabDecalage
                            Rect_Angle.Y = Rect.Y + Rect.Height - _Int_TabPath_Diametre
                            Path.AddArc(Rect_Angle, 30, 60)

                            Rect_Angle.X = Rect.X + _Int_TabDecalage
                            Path.AddArc(Rect_Angle, 90, 90)
                            Exit Select
                        Case Else
                            Rect_Angle.X = Rect.Left + _Int_TabDecalage + _Int_TabPath_Diametre + 5
                            Path.AddArc(Rect_Angle, 210, 60)

                            Rect_Angle.X = Rect.Right - _Int_TabPath_Diametre
                            Path.AddArc(Rect_Angle, 270, 90)

                            Path.AddLine(Rect.X + Rect.Width, Rect.Y + Rect.Height, Rect.X + _Int_TabDecalage, Rect.Y + Rect.Height)
                            Exit Select
                    End Select
                    Exit Select
            End Select

            'Ajout de G_Path à MyRegion
            'If myRegion Is Nothing Then
            ' myRegion = New Region(Path)
            'Else
            'myRegion.Union(New Region(Path))
            'End If

            Path.CloseFigure()

            'Path.Widen(New Pen(Color.Blue, 1))
            'Ajout de G_Path à MyRegion
            If myRegion Is Nothing Then
                myRegion = New Region(Path)
            Else
                myRegion.Union(New Region(Path))
            End If

            Dim path2 As New GraphicsPath
            path2 = Path.Clone
            path2.Widen(New Pen(Color.Blue, 1))
            myRegion.Union(path2)

            Return Path
        Finally
            Path = Nothing
        End Try
    End Function

    Public Overrides ReadOnly Property DisplayRectangle() As System.Drawing.Rectangle
        Get
            Return New Rectangle(GetTabRect(0).X, _
                                 GetTabRect(0).Y + GetTabRect(0).Height, _
                                 Me.Width - GetTabRect(0).X, _
                                 Me.Height - (GetTabRect(0).Y + GetTabRect(0).Height))
        End Get
    End Property

#End Region



    Private Sub PTIC_TabControl_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.SelectedIndexChanged
        Me.Invalidate()
    End Sub

End Class
